package concurrecy.lock3;

import java.util.concurrent.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockTest {
    final static int NR = 10; // 读线程数
    final static int NW = 1; // 写线程数
    final static int N = 10;

    static int i = 0;
//    private static Lock lock = new ReentrantLock();
//    private static Lock readLock = lock, writeLock = lock; // 用同一把锁控制读和写

//    private static ReadWriteLock lock = new ReentrantReadWriteLock();
    private static ReadWriteLock lock = new JannaReentrantReadWrite();
    private static Lock readLock = lock.readLock(), writeLock = lock.writeLock(); // 用读写锁控制读和写

    static void increment() {
        writeLock.lock();
        try {
            i++;
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            writeLock.unlock();
        }
    }

    static void get() {
        readLock.lock();
        try {
            int c = i;
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            readLock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(NR + NW);
        CyclicBarrier barrier = new CyclicBarrier(NR + NW);
        ExecutorService executorService = Executors.newCachedThreadPool();
        long point = System.currentTimeMillis();
        for (int j = 0; j < NW; j++) {
            executorService.execute(() -> {
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                for (int k = 0; k < N; k++) {
                    increment();
                }
                latch.countDown();
            });
        }
        for (int i = 0; i < NR; i++) {
            executorService.execute(() -> {
                try {
                    barrier.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (BrokenBarrierException e) {
                    e.printStackTrace();
                }
                for (int j = 0; j < N; j++) {
                    get();
                }
                latch.countDown();
            });
        }
        latch.await();
        System.out.println("use -> " + (System.currentTimeMillis() - point));
        System.out.println(i);
        executorService.shutdown();
    }
}
